#import "ALDetailViewController.h"
#import "ALEventViewController.h"
#import "ALTimelineViewController.h"
#import "ALChartViewController.h"
#import "NSObject+BlockObservation.h"
#import "NSManagedObjectContext+SMRAdditions.h"
#import "ALEntryFilter.h"


@interface ALDetailViewController ()
@property (nonatomic, retain) XSViewController *currentSubviewController;
-(void)switchToMode_:(ALDetailMode)mode;
-(NSPredicate *)versionsPredicate_;
-(NSPredicate *)selectedAppPredicate_;
-(NSPredicate *)selectedEntryFilterPredicate_;
-(void)filterEntries_;
-(ALVersionsFilterMode)filterModeForDetailMode:(ALDetailMode)detailMode;
@end


#pragma mark -
@implementation ALDetailViewController

@synthesize entriesArrayController;
@synthesize eventViewController;
@synthesize timelineViewController;
@synthesize chartViewController;
@synthesize currentSubviewController;


-(void)awakeFromNib {
    AMBlockTask versionsFilterTask = ^(id object, NSDictionary *change) {
//        [self updateVersionsFilter_];
//        [self updateSelectedAppsFilter_];
        [self filterEntries_];
    };
    for (NSUInteger detailMode = kALMinDetailMode; detailMode <= kALMaxDetailMode; detailMode++) {
        NSString *versionsFilterKeyPath = [NSString stringWithFormat:@"values.%@%ld", kALVersionsFilterKey, detailMode];
        [[NSUserDefaultsController sharedUserDefaultsController] addObserverForKeyPath:versionsFilterKeyPath task:versionsFilterTask];
    }
    NSString *modeSelectionKeyPath = [NSString stringWithFormat:@"values.%@", ALModeSelection];
    NSString *appSelectionKeyPath = [NSString stringWithFormat:@"values.%@", kALSelectedAppsKey];
    NSString *entryFilterSelectionKeyPath = [NSString stringWithFormat:@"values.%@", kALSelectedEntryFilterTitleKey];
    [[NSUserDefaultsController sharedUserDefaultsController] addObserverForKeyPath:modeSelectionKeyPath task:versionsFilterTask];
    [[NSUserDefaultsController sharedUserDefaultsController] addObserverForKeyPath:appSelectionKeyPath task:versionsFilterTask];
    [[NSUserDefaultsController sharedUserDefaultsController] addObserverForKeyPath:entryFilterSelectionKeyPath task:versionsFilterTask];
//    versionsFilterTask(nil, nil);
    
	ALDetailMode detailMode = (ALDetailMode)[[NSUserDefaults standardUserDefaults] integerForKey:ALModeSelection];
	[self switchToMode_:detailMode];
}


#pragma mark -
#pragma mark Accessors

-(ALEventViewController *)eventViewController {
	if (!eventViewController) {
		eventViewController = [[ALEventViewController alloc] initWithNibName:@"EventView" bundle:[NSBundle mainBundle] windowController:[self windowController] managedObjectContext:[self managedObjectContext]];
        [eventViewController setEntriesArrayController:[self entriesArrayController]];
	}
	return eventViewController;
}

-(ALTimelineViewController *)timelineViewController {
	if (!timelineViewController) {
		timelineViewController = [[ALTimelineViewController alloc] initWithNibName:@"TimelineView" bundle:[NSBundle mainBundle] windowController:[self windowController] managedObjectContext:[self managedObjectContext]];
        [timelineViewController setEntriesArrayController:[self entriesArrayController]];
	}
	return timelineViewController;
}

-(ALChartViewController *)chartViewController {
	if (!chartViewController) {
		chartViewController = [[ALChartViewController alloc] initWithNibName:@"ChartView" bundle:[NSBundle mainBundle] windowController:[self windowController] managedObjectContext:[self managedObjectContext]];
	}
	return chartViewController;
}


#pragma mark -
#pragma mark Actions

-(IBAction)toggleQuickLook:(id)sender {
	QLPreviewPanel *previewPanel = [QLPreviewPanel sharedPreviewPanel];
	if ([QLPreviewPanel sharedPreviewPanelExists] && [previewPanel isVisible])
		[previewPanel orderOut:self];
	else 
		[previewPanel makeKeyAndOrderFront:self];
}

-(IBAction)segmentedControlSwitchDetailMode:(id)sender {
	NSInteger selectedSegment = [sender selectedSegment];
	NSInteger tag = [[sender cell] tagForSegment:selectedSegment];
	[self switchToMode_:(ALDetailMode)tag];
}

-(IBAction)switchToEventMode:(id)sender {
	
}

-(IBAction)switchToTimelineMode:(id)sender {
	
}


#pragma mark -
#pragma mark Private methods

-(void)switchToMode_:(ALDetailMode)mode {
    XSViewController *currentController = [self currentSubviewController];
    [[currentController view] removeFromSuperview];
	XSViewController *newController = nil;
	switch (mode) {
		case ALModeEvent:
			newController = [self eventViewController];
			break;
		case ALModeTimeline:
			newController = [self timelineViewController];
			break;
		case ALModeChart:
			newController = [self chartViewController];
		default:
			break;
	}
	if (currentController)
		[self removeChild:currentController];
	if (newController)
		[self addChild:newController];
	[self setCurrentSubviewController:newController];
	NSView *newModeView = [newController view];
	[newModeView setFrame:[[self view] bounds]];
	[[self view] addSubview:newModeView];
//	[[NSUserDefaults standardUserDefaults] setInteger:mode forKey:ALModeSelection];
	NSDictionary *userInfo = [NSDictionary dictionaryWithObject:[NSNumber numberWithInteger:mode] forKey:ALNewMode];
	NSNotificationCenter *noteCenter = [NSNotificationCenter defaultCenter];
	[noteCenter postNotificationName:ALModeDidChangeNotification object:self userInfo:userInfo];
}

-(void)filterEntries_ {
    NSMutableArray *subpredicates = [NSMutableArray arrayWithCapacity:3];
    NSPredicate *appSubpredicate = [self selectedAppPredicate_];
    if (appSubpredicate)
        [subpredicates addObject:appSubpredicate];
    NSPredicate *versionSubpredicate = [self versionsPredicate_];
    if (versionSubpredicate)
        [subpredicates addObject:versionSubpredicate];
    NSPredicate *entryFilterSubpredicate = [self selectedEntryFilterPredicate_];
    if (entryFilterSubpredicate)
        [subpredicates addObject:entryFilterSubpredicate];
    NSPredicate *filterPredicate = [NSCompoundPredicate andPredicateWithSubpredicates:subpredicates];
    [[self entriesArrayController] setFilterPredicate:filterPredicate];
}

-(NSPredicate *)versionsPredicate_ {
    NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
    ALDetailMode currentDetailMode = (ALDetailMode)[userDefaults integerForKey:ALModeSelection];
    ALVersionsFilterMode filterMode = [self filterModeForDetailMode:currentDetailMode];

    NSPredicate *filterPredicate = nil;
    NSData *begin = nil, *end = nil;
    NSDate *beginDate = nil, *endDate = nil;
    NSArray *filterDates = nil;
    switch (filterMode) {
        case ALVersionsFilterModeCurrent:
            filterPredicate = [NSPredicate predicateWithFormat:@"version.currentApp != nil"];
            break;
        case ALVersionsFilterModeDate:
            begin = [[NSUserDefaults standardUserDefaults] objectForKey:kALVersionsFilterBeginDateKey];
            if (begin) beginDate = [NSKeyedUnarchiver unarchiveObjectWithData:begin];
            if (!beginDate)
                beginDate = [NSDate distantPast];
            end = [[NSUserDefaults standardUserDefaults] objectForKey:kALVersionsFilterEndDateKey];
            if (end) endDate = [NSKeyedUnarchiver unarchiveObjectWithData:end];
            if (!endDate)
                endDate = [NSDate distantFuture];
            filterDates = [NSArray arrayWithObjects:beginDate, endDate, nil];
            filterPredicate = [NSPredicate predicateWithFormat:@"version.releaseDate BETWEEN %@", filterDates];
            break;
        default:  // ALVersionsFilterModeAll will leave filterPredicate == nil
            break;
    }
    return filterPredicate;
}

-(NSPredicate *)selectedAppPredicate_ {
    NSArray *selectedAppURIStrings = [[NSUserDefaults standardUserDefaults] arrayForKey:kALSelectedAppsKey];
    NSArray *selectedApps = [[self managedObjectContext] smrObjectsWithURIStrings:selectedAppURIStrings];
    NSPredicate *predicate = [NSPredicate predicateWithFormat:@"version.app IN %@", selectedApps];
    return predicate;
}

-(NSPredicate *)selectedEntryFilterPredicate_ {
    NSString *selectedFilterTitle = [[NSUserDefaults standardUserDefaults] stringForKey:kALSelectedEntryFilterTitleKey];
    ALEntryFilter *entryFilter = [[self managedObjectContext] smrFetchFirstObjectForEntityName:[ALEntryFilter entityName] withPredicate:@"title LIKE %@", selectedFilterTitle];
    NSData *predicateData = [entryFilter predicate];
    if (!predicateData)
        return nil;
    NSPredicate *predicate = [NSKeyedUnarchiver unarchiveObjectWithData:predicateData];
    return predicate;
}

-(ALVersionsFilterMode)filterModeForDetailMode:(ALDetailMode)detailMode {
    NSString *defaultsKey = [NSString stringWithFormat:@"%@%ld", kALVersionsFilterKey, detailMode];
    return (ALVersionsFilterMode)[[NSUserDefaults standardUserDefaults] integerForKey:defaultsKey];
}

@end
